#pragma once

#include <chrono>
#include <functional>
#include <set>

#include <sys/epoll.h>
#include <memory>
#include <iostream>

/*
实现高效灵活的定时器
1. 定时器有哪些实现方式
2. 定时器与其他模块的关系
3. 定时接口设计
4. C++ STL容器选择 (map、multimap、set、multiset)
5. 容器中红黑树实现
6. 代码实现
*/

// 优化: 将用于比较的字段作为基础数据结构
struct TimerNodeBase
{
    time_t expire;  // 过期时间
    int64_t id;     // 唯一标识
};
// C++14 新特性 find()

struct TimerNode : public TimerNodeBase
{
    using Callback = std::function<void(const TimerNode& node)>;
    Callback func;  // 回调方法
    // 扩展:如果需要一直执行(可以添加always是否一直执行标志和gap记录定时执行间隔时间)
    bool always;
    time_t gap;
};

// 利用了多态实现的比较函数 timernodebase和timernode可以任意传入
inline bool operator<(const TimerNodeBase& lhd, const TimerNodeBase& rhd)
{
    if (lhd.expire < rhd.expire)
        return true;
    else if (lhd.expire > rhd.expire)
        return false;
    return lhd.id < rhd.id;     // 此时 expier 相等, id小的放在左边(先插入的任务放在左边)
}

class Timer
{
public:
    // 获取系统启动到现在的时间戳,单位:毫秒
    static time_t GetTick();

    static int64_t GenID();

    // 添加定时器
    TimerNodeBase AddTimer(time_t msec, TimerNode::Callback func, bool always = false);

    // 删除定时器
    bool DelTimer(TimerNodeBase& node);

    // 检查定时器
    bool CheckTimer();

    // 最近触发的定时任务离当前还要多久
    time_t TimeToSleep();

private:
    static int64_t gid;
    std::set<TimerNode, std::less<>> timermap;
};